using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Vin.Tool.AspNetCore.Singleton;
using Vin.Tool.Attributes;
using Vin.Tool.Core.AssemblyCategory;

namespace Vin.DependencyInjection.Core.Extension;

public static class OptionExtension
{
    public static void AddVinOptions(this IServiceCollection serviceCollection)
    {
        var allOptions = AssemblyTool.GetTypesByAttribute<OptionAttribute>()
            .Select(m => new
            {
                type = m,
                attr = m.GetCustomAttributes<OptionAttribute>().FirstOrDefault()!,
            });

        foreach (var option in allOptions)
        {
            var configurationChangeTokenSource = typeof(ConfigurationChangeTokenSource<>).MakeGenericType(option.type);
            var namedConfigureFromConfigurationOptions =
                typeof(NamedConfigureFromConfigurationOptions<>).MakeGenericType(option.type);
            var configureOptions = typeof(IConfigureOptions<>).MakeGenericType(option.type);
            var optionsChangeTokenSource = typeof(IOptionsChangeTokenSource<>).MakeGenericType(option.type);

            serviceCollection.AddOptions();
            serviceCollection.AddSingleton(optionsChangeTokenSource,
                Activator.CreateInstance(configurationChangeTokenSource, Options.DefaultName,
                    VinApp.Configuration.GetSection(option.attr.Key))!);
            serviceCollection.AddSingleton(configureOptions,
                Activator.CreateInstance(namedConfigureFromConfigurationOptions, Options.DefaultName,
                    VinApp.Configuration.GetSection(option.attr.Key))!);
        }
    }
}